package vue.panneau2.vue;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JPanel;

import vue.panneau2.modele.ModelePanneau2;
import vue.panneau2.modele.exception.IndiceIncorrectException;

public class PanneauRepresentation extends JPanel {
	private static final long serialVersionUID = 1L;
	private static final float TAILLELIGNE = 30f;
	private static final float TAILLECOL = 120f;
	private static final float DECALMATVERTICAL = 30f;
	private static final float DECALMATHORIZONTAL = 20f;
	private int nbLignes = 0;
	private int nbColonnes = 0;
	private ModelePanneau2 modelePanneau2;
	//Active/desactive l'affichage des informations sur la methode du simplexe
	private boolean modeDebutant = true;
	private int maxY = 10;
	private int maxX = 10;
	
	public PanneauRepresentation(ModelePanneau2 modelePanneau2) {
		this.modelePanneau2 = modelePanneau2;
		
		setVisible(true);
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		//Activation antialiasing
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		try {
			if (modelePanneau2.getProblemeLineaire().isResolu()) {
				nbLignes = modelePanneau2.getProblemeLineaire().getNbLignesMatriceAugmentee();
				nbColonnes = modelePanneau2.getProblemeLineaire().getNbColonnesMatriceAugmentee();
				
				maxX = nbColonnes*(int)TAILLECOL+500;
				maxY = nbLignes*(int)TAILLELIGNE+500;

				/*
				 * On a depasse l'etape de conversion de base, affichage de la matrice augmentee
				 * et du choix du pivot
				 */
				if (modelePanneau2.getNumEtapeCourant() >= 0 && modelePanneau2.getNumEtapeCourant() < modelePanneau2.getProblemeLineaire().getnombreDeMatrices() - 1) {
					//Affiche la matrice ainsi que certaines informations liées
					dessineMatriceCoordonnees(g2d, 0.0f, 0.0f);
					g2d.translate(0f, nbLignes*TAILLELIGNE+250f);
				}

				//Affichage des informations supplementaires
				if (modeDebutant) {
					g2d.setColor(Color.BLACK);
					float decalText = 20f;
					for (String phrase : modelePanneau2.getProblemeLineaire().getPhraseExplicativeEtape(modelePanneau2.getNumEtapeCourant())) {
						g2d.drawString(phrase, 20f, decalText);
						maxY = (int)decalText+10+nbLignes*(int)TAILLELIGNE+500;
						decalText += 20f;
					}
				}
			} else {
				g2d.setFont(new Font("Helvetica", Font.BOLD, 16));
				g2d.drawString("Problème non résolu", getWidth()/2, getHeight()/2);
			}
		} catch (IndiceIncorrectException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Affiche la matrice ainsi que certaines informations liées.
	 * @param g2d Le contexte graphique qui va recevoir l'affichage de la matrice.
	 * @param nbLignes Le nombre de lignes de la matrice.
	 * @param nbColonnes Le nombre de colonnes de la matrice.
	 * @throws IndiceIncorrectException Si on demande à accéder à une matrice en dehors des limites.
	 */
	public void dessineMatriceCoordonnees(Graphics2D g2d, float x, float y) throws IndiceIncorrectException {
		//Sauvegarde du contexte des transformations pour restauration ultérieure
		AffineTransform contexte = g2d.getTransform();
		
		//------------------------------------------------------------------------------------------
		//Trace des intitulés des colonnes
		int dimension = modelePanneau2.getProblemeLineaire().getDimension();
		int nbColMatAug = modelePanneau2.getProblemeLineaire().getNbColonnesMatriceAugmentee();
		
		//Les intitulés des variables nommées (hors base)
		for (int i = 0; i < dimension; i++) {
			g2d.drawString(modelePanneau2.getProblemeLineaire().getNomVariable(i), DECALMATHORIZONTAL+i*TAILLECOL+25f, DECALMATVERTICAL/2);
		}
		
		//Les intitulés des variables supplémentaires (variables de base)
		char c = 'M';
		for (int i = dimension; i < nbLignes+dimension; i++) {
			g2d.drawString(c++ + "", DECALMATHORIZONTAL+i*TAILLECOL+25f, DECALMATVERTICAL/2);
		}
		
		//Intitulé de la colonne "réponse"
		g2d.drawString("Réponse", DECALMATHORIZONTAL+25f+(dimension+nbLignes)*TAILLECOL, DECALMATVERTICAL/2);
		
		g2d.drawString("Calcul des ratios", DECALMATHORIZONTAL+nbColMatAug*TAILLECOL+20f, DECALMATVERTICAL/2);
		//------------------------------------------------------------------------------------------
		
		//------------------------------------------------------------------------------------------
		//Trace des accolades de la matrice
		BasicStroke stroke = new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
		g2d.setStroke(stroke);
		//Dessin de l'accolade de gauche
		g2d.draw(new QuadCurve2D.Float(DECALMATHORIZONTAL, DECALMATVERTICAL, DECALMATHORIZONTAL/2, (nbLignes*TAILLELIGNE)/2+DECALMATVERTICAL, DECALMATHORIZONTAL, nbLignes*TAILLELIGNE+DECALMATVERTICAL));
		//Dessin de l'accolade de droite
		g2d.draw(new QuadCurve2D.Float(nbColonnes*TAILLECOL+10f, DECALMATVERTICAL, nbColonnes*TAILLECOL+20f, (nbLignes*TAILLELIGNE)/2+DECALMATVERTICAL, nbColonnes*TAILLECOL+10f, nbLignes*TAILLELIGNE+DECALMATVERTICAL));
		//------------------------------------------------------------------------------------------
		
		//------------------------------------------------------------------------------------------
		//Trace de la ligne et de la colonne du pivot
		int pivotLigne = modelePanneau2.getProblemeLineaire().getPivotLigneEtape(modelePanneau2.getNumEtapeCourant());
		int pivotColonne = modelePanneau2.getProblemeLineaire().getPivotColonneEtape(modelePanneau2.getNumEtapeCourant());
		
		//La ligne du pivot
		g2d.setColor(new Color(0,200,0));
		g2d.draw(new Rectangle2D.Float(DECALMATHORIZONTAL+10f, pivotLigne*TAILLELIGNE+DECALMATVERTICAL, nbColonnes*TAILLECOL-25f, TAILLELIGNE));
		//La colonne du pivot
		g2d.setColor(Color.ORANGE);
		g2d.draw(new Rectangle2D.Float(pivotColonne*TAILLECOL+DECALMATHORIZONTAL+10f, DECALMATVERTICAL, TAILLECOL-25f, nbLignes*TAILLELIGNE));
		//------------------------------------------------------------------------------------------
		
		//------------------------------------------------------------------------------------------
		//Trace des valeurs de la matrice
		g2d.setColor(Color.BLACK);
		int i = 0, j = 0;
		for (ArrayList<Float> ligneMatrice : modelePanneau2.getProblemeLineaire().getMatriceAugmenteeEtape(modelePanneau2.getNumEtapeCourant())) {
			for (Float valeur : ligneMatrice) {
				g2d.drawString(valeur+"", (j*TAILLECOL+20f)+DECALMATHORIZONTAL, (i*TAILLELIGNE+20f)+DECALMATVERTICAL);
				j++;
			}
			i++;
			j = 0;
		}
		//------------------------------------------------------------------------------------------
		
		//------------------------------------------------------------------------------------------
		//Affichage des ratios
		ArrayList<String> ratiosEtape = modelePanneau2.getProblemeLineaire().getRatioMatriceEtape(modelePanneau2.getNumEtapeCourant());
		for (int l = 0; l < ratiosEtape.size(); l++) g2d.drawString(ratiosEtape.get(l), DECALMATHORIZONTAL+nbColMatAug*TAILLECOL+20f, (l*TAILLELIGNE+20f)+DECALMATVERTICAL);
		//------------------------------------------------------------------------------------------
		
		//------------------------------------------------------------------------------------------
		//Affichage du pivotage
		float xCadre = pivotColonne*TAILLECOL+TAILLECOL;
		float yCadre = nbLignes*TAILLELIGNE+DECALMATVERTICAL+50f;
		
		g2d.setColor(Color.ORANGE);
		//La ligne de jointure
		g2d.draw(new Line2D.Float(DECALMATHORIZONTAL+pivotColonne*TAILLECOL+TAILLECOL/2, nbLignes*TAILLELIGNE+DECALMATVERTICAL, xCadre, yCadre));
		//Le cadre pour afficher les résultats
		g2d.draw(new Rectangle2D.Float(xCadre, yCadre, TAILLECOL+100f, TAILLELIGNE*nbLignes));
		
		g2d.setColor(Color.BLACK);
		//Les formules de pivotage
		ArrayList<String> pivotEtape = modelePanneau2.getProblemeLineaire().getPivotageEtape(modelePanneau2.getNumEtapeCourant());
		for (int l = 0; l < pivotEtape.size(); l++) g2d.drawString(pivotEtape.get(l), xCadre+10f, (l*TAILLELIGNE+20f)+yCadre);
		//------------------------------------------------------------------------------------------
		
		//Restauration du contexte
		g2d.setTransform(contexte);
	}

	@Override
	public Dimension getPreferredSize() {
		return new Dimension(maxX,maxY);
	}
}
